package com.starlink.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.starlink.common.annotation.client.weixin.*;
import com.starlink.common.config.WechatConfigurationConfig;
import com.starlink.common.enums.OrderTypeEnum;
import com.starlink.common.exception.BusinessException;
import com.starlink.common.strategy.IPayNotify;
import com.starlink.common.strategy.PayNotifyHandlerContext;
import com.starlink.model.request.mall.WechatPay;
import com.starlink.model.request.mall.WechatRefund;
import com.starlink.service.WechatPayService;
import com.starlink.utils.AesUtil;
import com.starlink.utils.FastJsonUtils;
import com.starlink.utils.IRedisCacheService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

import static com.starlink.common.enums.RedisHashKeyEnum.ORDER_REFUND;

@Slf4j
@Service
public class WechatPayServiceImpl implements WechatPayService {

    @Autowired
    private PayNotifyHandlerContext payNotifyHandlerContext;
    @Autowired
    private IRedisCacheService redisCacheService;

    @Override
    public WeixinPayNotifyRes wxPayNotify(WeixinPayNotifyReq req) {
        try {
            //1.解析支付通知数据：得到业务侧商户订单号
            WeixinPayNotifyReq.Resource resource = req.getResource();
            if (resource == null) {
                return WeixinPayNotifyRes.ERR_RES;
            }
            String decryptStr = AesUtil.decryptToString(resource.getAssociated_data().getBytes(Charset.forName("UTF-8")),
                    resource.getNonce().getBytes(Charset.forName("UTF-8")),
                    resource.getCiphertext(),
                    WechatConfigurationConfig.wxUserWechatApiV3Key);
            log.info("wxPayNotify decryptStr: {}", decryptStr);
            WeixinPayNotifyReq.DecryptResource decryptResource = FastJsonUtils.fromJSONString(decryptStr, WeixinPayNotifyReq.DecryptResource.class);
            if (!"SUCCESS".equalsIgnoreCase(decryptResource.getTrade_state())) {
                log.info("wxPayNotify 支付订单状态不成功");
                return WeixinPayNotifyRes.ERR_RES;
            }

            //2.查询订单数据
            String attach = decryptResource.getAttach();
            WechatPay wechatPay = JSONObject.parseObject(attach, WechatPay.class);
            String orderType = wechatPay.getOrderType().toString();
            String orderNum = decryptResource.getOut_trade_no();
            if (StringUtils.isAnyBlank(orderType, orderNum)) {
                log.error("wxPayNotify 商户系统订单号编号or订单类型为空 mainOrderNum={} payOrderType={}", orderNum, orderType);
                return WeixinPayNotifyRes.ERR_RES;
            }

            OrderTypeEnum payOrderNumType = OrderTypeEnum.getByType(Integer.parseInt(orderType));
            if (payOrderNumType == null) {
                log.error("wxPayNotify 商户系统订单类型非法 payOrderType={}", orderType);
                return WeixinPayNotifyRes.ERR_RES;
            }
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
            Date paymentDate = dateFormat.parse(decryptResource.getSuccess_time());
            wechatPay.setPayType("微信支付");
            wechatPay.setPaymentDate(paymentDate);
            wechatPay.setOrderNum(orderNum);
            wechatPay.setWeChatOrderId(decryptResource.getTransaction_id());
            payNotifyHandlerContext.handle(payOrderNumType, wechatPay);
        } catch (BusinessException e) {
            log.error("wxPayNotify 微信支付回调业务异常 errorMessage: {}", e.getMessage(), e);
            return WeixinPayNotifyRes.ERR_RES;
        } catch (Exception e) {
            log.error("wxPayNotify 微信支付回调系统异常 errorMessage: {}", e.getMessage(), e);
            return WeixinPayNotifyRes.ERR_RES;
        }
        return WeixinPayNotifyRes.SUC_RES;
    }

    @Override
    public WeixinRefundNotifyRes wxRefundNotify(WeixinRefundNotifyReq req) {
        try {
            //1.解析退款通知数据：得到业务侧商户退款单号
            WeixinRefundNotifyReq.Resource resource = req.getResource();
            if (resource == null) {
                return WeixinRefundNotifyRes.ERR_RES;
            }
            String decryptStr = AesUtil.decryptToString(resource.getAssociated_data().getBytes(Charset.forName("UTF-8")),
                    resource.getNonce().getBytes(Charset.forName("UTF-8")),
                    resource.getCiphertext(),
                    WechatConfigurationConfig.wxUserWechatApiV3Key);
            log.info("wxRefundNotify decryptStr: {}", decryptStr);
            WeixinRefundNotifyReq.DecryptResource decryptResource = FastJsonUtils.fromJSONString(decryptStr, WeixinRefundNotifyReq.DecryptResource.class);
            if (!"SUCCESS".equalsIgnoreCase(decryptResource.getRefund_status())) {
                log.info("wxRefundNotify 退款订单状态不成功");
                return WeixinRefundNotifyRes.ERR_RES;
            }

            //2.查询退款订单数据
            String refundOrderNum = decryptResource.getOut_refund_no();
            if (StringUtils.isBlank(refundOrderNum)) {
                log.error("wxRefundNotify 微信返回的商户系统out_refund_no订单号为空");
                return WeixinRefundNotifyRes.ERR_RES;
            }

            WechatRefund wechatRefund = redisCacheService.hashGet(ORDER_REFUND.name(), refundOrderNum);
            OrderTypeEnum orderTypeEnum = OrderTypeEnum.getByType(wechatRefund.getOrderType());
            if (orderTypeEnum == null) {
                log.error("wxPayNotify 商户系统订单类型非法 orderType={}", wechatRefund.getOrderType());
                return WeixinRefundNotifyRes.ERR_RES;
            }
            wechatRefund.setWxRefundNum(decryptResource.getRefund_id());
            wechatRefund.setTotal(decryptResource.getAmount().getTotal());
            wechatRefund.setRefund(decryptResource.getAmount().getRefund());
            wechatRefund.setPayerTotal(decryptResource.getAmount().getPayer_total());
            wechatRefund.setPayerRefund(decryptResource.getAmount().getPayer_refund());
            payNotifyHandlerContext.refundHandle(orderTypeEnum, wechatRefund);
        } catch (BusinessException e) {
            log.error("wxPayNotify 微信退款回调业务异常 errorMessage: {}", e.getMessage(), e);
            return WeixinRefundNotifyRes.ERR_RES;
        } catch (Exception e) {
            log.error("wxPayNotify 微信退款回调系统异常 errorMessage: {}", e.getMessage(), e);
            return WeixinRefundNotifyRes.ERR_RES;
        }
        return WeixinRefundNotifyRes.SUC_RES;
    }
}
